﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using Hank.BrowserParse;
using HAF.FoundationLib;
using Newtonsoft.Json;
using WareDealer.Helper;
using WareDealer.Mode;

namespace WareDealer
{
    /// <summary>
    /// 价格采集任务
    /// </summary>
    [DisplayName("价格采集工作项")]
    public class JdPriceWork : IWorkItem
    {
        /// <summary>
        /// 编号
        /// </summary>
        public int ID { get; set; }
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 优先级
        /// </summary>
        public int Priority { get; set; }
        /// <summary>
        /// 工作内容
        /// </summary>
        public Object WorkItems { get; set; }
        /// <summary>
        /// 状态
        /// </summary>
        public EnumGatherStatu Statu { get; internal set; }
        /// <summary>
        /// 返回结果集
        /// </summary>
        public object ResultItems { get; internal set; }

        /// <summary>
        /// 时长
        /// </summary>
        public int Time { get; set; }

        /// <summary>
        /// 执行函数
        /// </summary>
        public void ExecItem()
        {
            List<ProductInfo> wares = WorkItems as List<ProductInfo>;
            if (wares == null || wares.Count <= 0) return;
            Statu = EnumGatherStatu.Begin;
            List<string> wList = wares.Select(item => item.ProductID).ToList();
            _waresPrice.Clear();
            foreach (var item in wares)
            {
                _waresPrice.Add(new JdWarePriceCache()
                {
                    Skuid = item.ProductID,
                    LastPrice = item.ProductLastPrice,
                    TodayPrevPrice = item.ProductTodayPrice,
                    PriceTrend = item.ProductPriceTrend,
                    MinPrice = item.ProductMinPrice,
                    LastMinPrice = item.ProductMinPrice,
                    MinPriceSrc = item.ProductPriceType,
                    MaxPrice = item.ProductMaxPrice,
                    LastMaxPrice = item.ProductMaxPrice,
                    AppPrice = item.ProductMobilePrice,
                    WebPrice = item.ProductPrice,
                    QqPrice = item.ProductQQPrice,
                    WxPrice = item.ProductWXPrice,
                    IsWebChange = false,
                    IsAppChange = false,
                    IsQqChange = false,
                    IsWxChange = false,
                    PriceGatherDate = item.ProductPriceDate
                });
            }
            
            GetBatchWarePrice(wList);
        }

        private readonly List<JdWarePriceCache> _waresPrice = new List<JdWarePriceCache>();
        /// <summary>
        /// 批量价格获取
        /// </summary>
        /// <param name="pids">商品编号集合</param>
        [DisplayName("批量价格更新")]
        private void GetBatchWarePrice(List<string> pids)
        {
            Faster.XLogInfo(string.Format("批量采集价格{0}更新开始", Name));
            
            //https://pm.3.cn/prices/mgets?origin=2&skuids=1309453,1713088,1191695
            //[{"id":"1309453","p":"209.00","m":"328.00"},{"id":"1713088","p":"118.00","m":"208.00"},{"id":"1191695","p":"148.00","m":"268.00"}]
            if (pids != null && pids.Count > 0)
            {
                try
                {
                    Statu = EnumGatherStatu.Exec;
                    string skuids = string.Join(",J_", pids.ToArray());
                    //string skuids = string.Join(",", pids.ToArray());
                    //网站价格获取
                    //string url = string.Format("https://p.3.cn/prices/mgets?type=1&skuIds=J_{0}", skuids);
                    string url = "";
                    if (SysParams.AllowGetPrice)
                    {
                        url = string.Format("https://p.3.cn/prices/mgets?type=1&skuIds=J_{0}", skuids);
                        //url = string.Format("http://pm.3.cn/prices/pcpmgets?skuids={0}&origin=2&source=1&area=1_2800_4134_0&_={1}", skuids, GetTimeStamp());
                        BatchParse(url, WarePriceType.WebPrice);

                        List<JdWarePriceCache> tmpPrices = _waresPrice.FindAll(t => t.WebPrice == 0);
                        if (tmpPrices.Count > 10)
                        {
                            //如果价格为0的超过10个则跑另外一个批量采集接口
                            skuids = string.Join(",", pids.ToArray());
                            url = string.Format("http://pm.3.cn/prices/pcpmgets?skuids={0}&origin=2&source=1&area=1_2800_4134_0&_={1}", skuids, Golemer.GetTimeStamp());
                            BatchParse(url, WarePriceType.WebPrice);
                        }
                        
                    }

                    skuids = string.Join(",", pids.ToArray());
                    if (SysParams.AllowGetMobilePrice)
                    {
                        //手机平台价格获取
                        url = string.Format("https://pm.3.cn/prices/mgets?origin=2&skuids={0}", skuids);
                        BatchParse(url, WarePriceType.AppPrice);
                    }

                    if (SysParams.AllowGetQQPrice)
                    {
                        //QQ平台价格获取
                        url = string.Format("https://pe.3.cn/prices/mgets?origin=4&skuids={0}", skuids);
                        BatchParse(url, WarePriceType.QQPrice);
                    }

                    if (SysParams.AllowGetWXPrice)
                    {
                        //微信平台价格获取
                        url = string.Format("https://pe.3.cn/prices/mgets?origin=5&skuids={0}", skuids);
                        BatchParse(url, WarePriceType.WxPrice);
                    }

                    //底价及价格趋势处理
                    foreach (var priceItem in _waresPrice)
                    {
                        GetMinPriceSrc(priceItem);
                        GetPriceTrend(priceItem);
                    }
                    ResultItems = _waresPrice;

                }
                catch (Exception ex)
                {
                    Faster.XLogErr(ex.Message);
                }
            }
            Statu = EnumGatherStatu.End;
            Faster.XLogInfo(string.Format("批量采集价格{0}更新结束", Name));
        }

        private JdWarePrice GetMinPriceSrc(double price1, double price2, double price3, double price4)
        {
            JdWarePrice tmpJDPrice = new JdWarePrice();
            tmpJDPrice.p = price1.ToString();
            tmpJDPrice.src = "京东";
            //加入double数组
            double[] listPrice = new double[4];
            listPrice[0] = price1;
            listPrice[1] = price2;
            listPrice[2] = price3;
            listPrice[3] = price4;

            //存储临时的需要冒泡的值
            double tempPrice = listPrice.Max();

            for (int i = 0; i < listPrice.Length; i++)
            {
                //当值为0或-1时，取最大值代替
                if (listPrice[i] == 0 || listPrice[i] == -1)
                {
                    listPrice[i] = tempPrice;
                }
            }

            //tempPrice = listPrice.Min();

            tempPrice = listPrice[0];
            //价格索引，用于判断是哪个平台价格最低
            int tempIndex = 0;
            //从数组的第一个值遍历到倒数第二个值
            for (int i = 1; i < listPrice.Length; i++)
            {
                if (listPrice[i] < tempPrice)
                {
                    tempPrice = listPrice[i];
                    tempIndex = i;
                }
                ////从比i大1的值开始遍历到结束
                ////这里比较的总是比i大的值，因为之前的值已经冒泡完成
                //for (int j = i + 1; j < listPrice.Length; j++)
                //{
                //    //如果前一个值大于后一个值，他们交换位置
                //    if (listPrice[i] > listPrice[j])
                //    {
                //        //交换位置
                //        tempPrice = listPrice[i];
                //        listPrice[i] = listPrice[j];
                //        listPrice[j] = tempPrice;
                //    }
                //}
            }
            switch (tempIndex)
            {
                case 0:
                    tmpJDPrice.src = "京东";
                    break;
                case 1:
                    tmpJDPrice.src = "手机";
                    break;
                case 2:
                    tmpJDPrice.src = "QQ";
                    break;
                case 3:
                    tmpJDPrice.src = "微信";
                    break;
            }
            tmpJDPrice.p = tempPrice.ToString();

            return tmpJDPrice;
        }

        /// <summary>
        /// 获取当次采集最小值
        /// </summary>
        /// <param name="jdWarePrice"></param>
        private void GetMinPriceSrc(JdWarePriceCache jdWarePrice)
        {
            if (jdWarePrice == null) return;
            jdWarePrice.MinPrice = 0;
            jdWarePrice.MinPriceSrc = "京东";
            //加入double数组
            double[] listPrice = new double[4];
            listPrice[0] = jdWarePrice.WebPrice;
            listPrice[1] = jdWarePrice.AppPrice;
            listPrice[2] = jdWarePrice.QqPrice;
            listPrice[3] = jdWarePrice.WxPrice;

            //存储临时的需要冒泡的值
            double tempPrice = listPrice.Max();
            //获取当前最大值
            jdWarePrice.MaxPrice = tempPrice;
            if (jdWarePrice.LastMaxPrice < jdWarePrice.MaxPrice)
            {
                jdWarePrice.LastMaxPrice = jdWarePrice.MaxPrice;
            }

            for (int i = 0; i < listPrice.Length; i++)
            {
                //当值为0或-1时，取最大值代替
                if (listPrice[i] == 0 || listPrice[i] == -1)
                {
                    listPrice[i] = tempPrice;
                }
            }

            tempPrice = listPrice[0];
            //价格索引，用于判断是哪个平台价格最低
            int tempIndex = 0;
            //从数组的第一个值遍历到倒数第二个值
            //不用listPrice.Min是因为需要知道序号来判断来源
            for (int i = 1; i < listPrice.Length; i++)
            {
                if (listPrice[i] < tempPrice)
                {
                    tempPrice = listPrice[i];
                    tempIndex = i;
                }
                
                //从比i大1的值开始遍历到结束
                //这里比较的总是比i大的值，因为之前的值已经冒泡完成
                //for (int j = i + 1; j < listPrice.Length; j++)
                //{
                //    //如果前一个值大于后一个值，他们交换位置
                //    if (listPrice[i] > listPrice[j])
                //    {
                //        //交换位置
                //        tempPrice = listPrice[i];
                //        listPrice[i] = listPrice[j];
                //        listPrice[j] = tempPrice;
                //    }
                //}
            }
            switch (tempIndex)
            {
                case 0:
                    jdWarePrice.MinPriceSrc = "京东";
                    break;
                case 1:
                    jdWarePrice.MinPriceSrc = "手机";
                    break;
                case 2:
                    jdWarePrice.MinPriceSrc = "QQ";
                    break;
                case 3:
                    jdWarePrice.MinPriceSrc = "微信";
                    break;
            }
            jdWarePrice.MinPrice = tempPrice;
            jdWarePrice.LastMinPrice = jdWarePrice.LastMinPrice > tempPrice ? tempPrice : jdWarePrice.LastMinPrice;

        }
        /// <summary>
        /// 获取价格趋势
        /// </summary>
        /// <param name="jdWarePrice"></param>
        private void GetPriceTrend(JdWarePriceCache jdWarePrice)
        {
            if (jdWarePrice == null) return;
            jdWarePrice.PriceTrend = "未知";
            if (jdWarePrice.LastPrice == 0) return;

            if (jdWarePrice.MinPrice < jdWarePrice.TodayPrevPrice)
            {
                jdWarePrice.PriceTrend = "走低";
            }
            if (jdWarePrice.MinPrice > jdWarePrice.TodayPrevPrice)
            {
                jdWarePrice.PriceTrend = "涨价";
            }
            if (jdWarePrice.MinPrice == jdWarePrice.TodayPrevPrice )
            {
                jdWarePrice.PriceTrend = jdWarePrice.MinPrice == jdWarePrice.LastPrice ? "持平" : jdWarePrice.MinPrice > jdWarePrice.LastPrice ? "涨价" : "走低";
            }
        }
        
        /// <summary>
        /// 批价格解析
        /// </summary>
        /// <param name="url">访问网址</param>
        /// <param name="src">价格来源</param>
        [DisplayName("批价格解析")]
        private void BatchParse(string url, WarePriceType src)
        {
            try
            {
                string price = HttpHelper.GetResponseGBK(url, "get", string.Empty);
                if (string.IsNullOrEmpty(price) || price.IndexOf("error", StringComparison.Ordinal) >= 0)
                {
                    Faster.XLogInfo("获取价格失败!!!");
                    //获取价格失败则退出
                    return;
                }

                //网页价格
                List<JdWarePrice> jdPrices = JsonConvert.DeserializeObject<List<JdWarePrice>>(price);
                if (jdPrices != null && jdPrices.Count > 0)
                {
                    foreach (var item in jdPrices)
                    {
                        string pid = item.id.IndexOf('J') >= 0 ? item.id.Replace("J_", "") : item.id;
                        JdWarePriceCache tmpWare = _waresPrice.Find(t => t.Skuid == pid);
                        if (tmpWare == null)
                        {
                            tmpWare = new JdWarePriceCache {Skuid = pid};
                            _waresPrice.Add(tmpWare);
                        }
                        double rtnPrice = 0;
                        double.TryParse(item.p, out rtnPrice);
                        if (rtnPrice <= 0)
                        {
                            Faster.XLogInfo("当前价格为0");
                        }

                        switch (src)
                        {
                            case WarePriceType.WebPrice:
                                tmpWare.IsWebChange = tmpWare.PriceGatherDate.Date != DateTime.Now.Date || tmpWare.WebPrice != rtnPrice;
                                tmpWare.WebPrice = rtnPrice;
                                if (rtnPrice <= 0)
                                {
                                    Faster.XLogInfo(string.Format("当前商品网页价格为{0}", rtnPrice));
                                }
                                break;
                            case WarePriceType.AppPrice:
                                tmpWare.IsAppChange = tmpWare.PriceGatherDate.Date != DateTime.Now.Date || tmpWare.AppPrice != rtnPrice;
                                tmpWare.AppPrice = rtnPrice;
                                if (rtnPrice <= 0)
                                {
                                    Faster.XLogInfo(string.Format("当前商品手机价格为{0}", rtnPrice));
                                }
                                break;
                            case WarePriceType.QQPrice:
                                tmpWare.IsQqChange = tmpWare.PriceGatherDate.Date != DateTime.Now.Date || tmpWare.QqPrice != rtnPrice;
                                tmpWare.QqPrice = rtnPrice;
                                if (rtnPrice <= 0)
                                {
                                    Faster.XLogInfo(string.Format("当前商品QQ价格为{0}", rtnPrice));
                                }
                                break;
                            case WarePriceType.WxPrice:
                                tmpWare.IsWxChange = tmpWare.PriceGatherDate.Date != DateTime.Now.Date || tmpWare.WxPrice != rtnPrice;
                                tmpWare.WxPrice = rtnPrice;
                                if (rtnPrice <= 0)
                                {
                                    Faster.XLogInfo(string.Format("当前商品微信价格为{0}", rtnPrice));
                                }
                                break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Faster.XLogErr(ex.Message);
            }

        }
    }
    /// <summary>
    /// 库存采集任务
    /// </summary>
    [DisplayName("库存采集工作项")]
    public class JdStockWork : IWorkItem
    {
        /// <summary>
        /// 编号
        /// </summary>
        public int ID { get; set; }
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 优先级
        /// </summary>
        public int Priority { get; set; }
        /// <summary>
        /// 工作内容
        /// </summary>
        public Object WorkItems { get; set; }
        /// <summary>
        /// 状态
        /// </summary>
        public EnumGatherStatu Statu { get; internal set; }

        public object ResultItems { get; internal set; }
        /// <summary>
        /// 时长
        /// </summary>
        public int Time { get; set; }
        /// <summary>
        /// 最大处理数量
        /// </summary>
        private const int StockMaxLength = 30;

        readonly List<WareStock> _batchWareStocks = new List<WareStock>(); 
        /// <summary>
        /// 执行函数
        /// </summary>
        public void ExecItem()
        {
            List<ProductInfo> wares = WorkItems as List<ProductInfo>;
            if (wares == null || wares.Count <= 0) return;
            Statu = EnumGatherStatu.Begin;
            List<string> wStockIds = new List<string>();
            int i = 0;
            //var wStocks = WorkItems.Select(item => GetWareStock(item.ProductID, item.VenderId, item.Catalog)).Where(rtnStock => rtnStock != null).ToList();
            foreach (var item in wares)
            {
                if (i >= StockMaxLength)
                {
                    List<WareStock> wStocks = GetBatchWareStock(wStockIds);
                    if (wStocks != null && wStocks.Count > 0)
                    {
                        _batchWareStocks.AddRange(wStocks);
                    }
                    i = 0;
                    wStockIds.Clear();
                }
                wStockIds.Add(item.ProductID);
                i++;
                //WareStock rtnStock = GetWareStock(item.ProductID, item.VenderId, item.Catalog);
                //if (rtnStock != null)
                //{
                //    wStocks.Add(rtnStock);
                //}

            }
            //可能存在少于30的情况
            List<WareStock> wStocks1 = GetBatchWareStock(wStockIds);
            _batchWareStocks.AddRange(wStocks1);

            ResultItems = _batchWareStocks;
        }

        /// <summary>
        /// 获取库存信息
        /// </summary>
        /// <param name="skuId">商品编号</param>
        /// <param name="venderId">商家编号</param>
        /// <param name="category">分类</param>
        /// <returns></returns>
        private WareStock GetWareStock(string skuId, string venderId, string category)
        {
            try
            {
                WareStock rtnStock = null;
                //配送服务 22_1930_4283_0
                if (string.IsNullOrEmpty(category))
                {
                    category = "6144,12041,12047";
                }
                //http://ss.3.cn/ss/areaStockState/mget?app=search_pc&ch=1&skuNum=11968160;1069555;1510479;1601978;206737&area=22,1930,4283,0&callback=jQuery966382&_=1467106314590
                string urlService = "http://c0.3.cn/stock?skuId=" + skuId + "&venderId=" + venderId.Trim() + "&cat=" + category + "&area=" + SysParams.DispathArea
                    + "&buyNum=1&extraParam={%22originid%22:%221%22}&ch=1";

                string htmlService = HttpHelper.GetResponseGBK(urlService, "get", string.Empty);
                string strStock = htmlService.Replace("getStockCallback(", "").TrimEnd(')');
                if (string.IsNullOrEmpty(strStock))
                {
                    return null;
                }
                StockInfo jdStock = JsonConvert.DeserializeObject<StockInfo>(strStock);
                if (jdStock != null)
                {
                    rtnStock = new WareStock()
                    {
                        Skuid = skuId,
                        StockState = jdStock.Stock.StockState,
                        StockName = jdStock.Stock.StockStateName,
                        StockNum = jdStock.Stock.rn
                    };

                }
                return rtnStock;
            }
            catch (Exception ex)
            {
                Faster.XLogErr(ex.Message);
                return null;
            }

        }
        /// <summary>
        /// 批量获取库存信息
        /// </summary>
        /// <returns></returns>
        private List<WareStock> GetBatchWareStock(List<string> pids)
        {
            try
            {
                List<WareStock> rtnStocks = new List<WareStock>();
                Faster.XLogInfo(string.Format("批量采集库存{0}更新开始", Name));

                //http://ss.3.cn/ss/areaStockState/mget?app=search_pc&ch=1&skuNum=11968160;1069555;1510479;1601978;206737&area=22,1930,4283,0&callback=jQuery966382&_=1467106314590
                //http://ss.3.cn/ss/areaStockState/mget?app=list_pc&ch=1&skuNum=11968160;1069555;1510479;1601978;206737&area=22,1930,4283,0&callback=jQuery966382&_=1467106314590
                //[{"id":"1309453","p":"209.00","m":"328.00"},{"id":"1713088","p":"118.00","m":"208.00"},{"id":"1191695","p":"148.00","m":"268.00"}]
                if (pids != null && pids.Count > 0)
                {
                    try
                    {
                        Statu = EnumGatherStatu.Exec;
                        string skuids = string.Join(";", pids.ToArray());
                        string myArea = SysParams.DispathArea.Replace('_',',');
                        string url = string.Format("http://ss.3.cn/ss/areaStockState/mget?app=search_pc&ch=1&skuNum={0}&area={1}&_={2}", skuids, myArea, Golemer.GetTimeStamp(false));
                        //{"1069555":{"a":"34","b":"1","c":"-1","l":"0"},"11968160":{"a":"40","b":"1","c":"-1","l":"2"},
                        //"1510479":{"a":"33","b":"1","c":"-1","l":"0"},"1601978":{"a":"33","b":"1","c":"-1","l":"0"},"206737":{"a":"34","b":"1","c":"-1","l":"0"}}
                        string mystock = HttpHelper.GetResponseUTF(url, "get", string.Empty);
                        //string[] stocks = Regex.Split(mystock, "},", RegexOptions.IgnoreCase);
                        string[] stocks = mystock.Split(new string[] { "}," }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (var item in stocks)
                        {
                            string skuId = Regex.Match(item, "(\\d{6,14})").Value;
                            string tJsonTxt = Regex.Match(item, "\\{\"a.*").Value;
                            string cont = tJsonTxt.Replace("}}", "") + "}";
                            AreaStockState jdStock = JsonConvert.DeserializeObject<AreaStockState>(cont);

                            var rtnStock = new WareStock()
                            {
                                Skuid = skuId,
                                StockState = int.Parse(jdStock.a),
                                //StockName = jdStock.Stock.StockStateName,
                                StockNum = int.Parse(jdStock.l)
                            };
                            rtnStocks.Add(rtnStock);
                        }
                    }
                    catch (Exception ex)
                    {
                        Faster.XLogErr(ex.Message);
                    }
                }
                Statu = EnumGatherStatu.End;
                Faster.XLogInfo(string.Format("批量采集库存{0}更新结束", Name));
                return rtnStocks;
            }
            catch (Exception ex)
            {
                Statu = EnumGatherStatu.End;
                Faster.XLogErr(ex.Message);
                return null;
            }
        }

       public class AreaStockState
        {
            /// <summary>
            /// 库存状态
            /// </summary>
            /// <remarks>33 有货、34 无货、36 预订</remarks>
            public string a { get; set; }
            /// <summary>
            /// 1
            /// </summary>
            public string b { get; set; }
            /// <summary>
            /// 库存余量 -1、2、3、5
            /// </summary>
            public string c { get; set; }
            /// <summary>
            /// 到货日期
            /// </summary>
            public string j { get; set; }
            /// <summary>
            /// 0
            /// </summary>
            public string l { get; set; }
        }
    }
    /// <summary>
    /// 广告采集任务
    /// </summary>
    [DisplayName("促销采集工作项")]
    public class JdSubHeadWork : IWorkItem
    {
        /// <summary>
        /// 编号
        /// </summary>
        public int ID { get; set; }
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 优先级
        /// </summary>
        public int Priority { get; set; }
        /// <summary>
        /// 工作内容
        /// </summary>
        public Object WorkItems { get; set; }

        public object ResultItems { get; set; }
        /// <summary>
        /// 状态
        /// </summary>
        public EnumGatherStatu Statu { get; internal set; }
        /// <summary>
        /// 时长
        /// </summary>
        public int Time { get; set; }
        /// <summary>
        /// 执行函数
        /// </summary>
        public void ExecItem()
        {
            List<ProductInfo> wares = WorkItems as List<ProductInfo>;
            if (wares == null || wares.Count <= 0) return;
            Statu = EnumGatherStatu.Begin;

            List<string> wList = wares.Select(item => item.ProductID).ToList();
            GetWareAdMessage(wList);

        }
        [DisplayName("获取促销信息")]
        private void GetWareAdMessage(List<string> pids)
        {
            try
            {
                Faster.XLogInfo(string.Format("批量采集促销{0}更新开始", Name));
                if (pids != null && pids.Count > 0)
                {
                    string skuids = string.Join(",AD_", pids.ToArray());
                    string url = string.Format("http://ad.3.cn/ads/mgets?skuids={0}&_={1}", skuids, Golemer.GetTimeStamp());
                    string strCoupon = HttpHelper.GetResponseUTF(url, "get", string.Empty);
                    List<AdMessageTag> myCoupons = JsonConvert.DeserializeObject<List<AdMessageTag>>(strCoupon);
                    if (myCoupons != null && myCoupons.Count > 0)
                    {
                        foreach (var item in myCoupons)
                        {
                            item.ad = Golemer.ClearHtml(item.ad);
                            item.id = item.id.Replace("AD_", "");
                        }
                        ResultItems = myCoupons;
                    }
                }
                Statu = EnumGatherStatu.End;
                Faster.XLogInfo(string.Format("批量采集促销{0}更新结束", Name));
            }
            catch (Exception ex)
            {
                Statu = EnumGatherStatu.End;
                Faster.XLogErr(ex.Message);
            }
            
        }
    }
    /// <summary>
    /// 优惠采集任务
    /// </summary>
    [DisplayName("优惠采集工作项")]
    public class JdCouponWork : IWorkItem
    {
        /// <summary>
        /// 编号
        /// </summary>
        public int ID { get; set; }
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 优先级
        /// </summary>
        public int Priority { get; set; }
        /// <summary>
        /// 优惠信息集合
        /// </summary>
        private readonly List<PrivilegeTag> _promoList = new List<PrivilegeTag>();
        /// <summary>
        /// 工作内容
        /// </summary>
        public Object WorkItems { get; set; }
        /// <summary>
        /// 回馈对象集合
        /// </summary>
        public object ResultItems { get; set; }
        /// <summary>
        /// 状态
        /// </summary>
        public EnumGatherStatu Statu { get; internal set; }
        /// <summary>
        /// 时长
        /// </summary>
        public int Time { get; set; }
        /// <summary>
        /// 执行函数
        /// </summary>
        [DisplayName("执行函数")]
        public void ExecItem()
        {
            List<ProductInfo> _wareList = WorkItems as List<ProductInfo>;
            if (_wareList == null || _wareList.Count <= 0) return;
            Statu = EnumGatherStatu.Begin;

            Faster.XLogInfo(string.Format("批量采集优惠{0}更新开始", Name));

            _wareList.ForEach(t => _promoList.Add(new PrivilegeTag() { Sku = t.ProductID, Coupon = "", Promo = "", IsEnd = false }));
            
            int iSplit = 1;
            int iCount = 0;
            List<ProductInfo> splitWares = new List<ProductInfo>();
            foreach (var item in _wareList)
            {
                //GetPromoThread(item);
                //GetWarePromotion(item);
                splitWares.Add(item);
                iCount++;
                iSplit++;
                if (iSplit > 25 || (iCount == _wareList.Count && iSplit <= 25))
                {
                    GetPromoThread(splitWares);
                    splitWares = new List<ProductInfo>();
                    iSplit = 0;
                }
            }

            Stopwatch outManage = new Stopwatch();
            outManage.Start();
            while (true)
            {
                try
                {
                    List<PrivilegeTag> remainWares = _promoList.Where(t => t.IsEnd == false).ToList();
                    if (remainWares.Count == 0)
                    {
                        ResultItems = _promoList;
                        Statu = EnumGatherStatu.End;
                        Faster.XLogInfo(string.Format("批量采集优惠{0}更新完成", Name));
                        break;
                    }
                    else
                    {
                        if (outManage.ElapsedMilliseconds == 300000)
                        {
                            //超时控制5分钟
                            //超时自动设置所有采集为完成状态
                            _promoList.ForEach(t => t.IsEnd = true);
                        }
                    }
                    Thread.Sleep(1000);
                }
                catch (Exception ex)
                {
                    Faster.XLogErr(ex.Message);
                }
            }
            
        }

        private void GetPromoThread(List<ProductInfo> wares)
        {
            Thread promoThread = new Thread(delegate() { GetPromoBatch(wares); }) { Name = "promoThread" + wares[0].ProductID, IsBackground = true };
            promoThread.Start();
        }

        private void GetPromoBatch(List<ProductInfo> wares)
        {
            try
            {
                foreach (var item in wares)
                {
                    GetWarePromotion(item);
                    Thread.Sleep(100);
                }
            }
            catch (Exception ex)
            {
                Faster.XLogErr(ex.Message);
            }
            
        }

        /// <summary>
        /// 获取商品促销信息
        /// </summary>
        /// <param name="myProduct"></param>
        [DisplayName("获取商品促销信息")]
        private void GetWarePromotion(ProductInfo myProduct)
        {
            try
            {
                //http://cd.jd.com/promotion/v2?skuId=1579607941&area=1_72_2799_0&shopId=138013&venderId=142424&cat=1318%2C12102%2C9765&_=1459345921060
                
                PrivilegeTag nowTag = _promoList.Single(t => t.Sku == myProduct.ProductID);
                if (nowTag != null)
                {
                    string url = string.Format("http://cd.jd.com/promotion/v2?skuId={0}&area={1}&shopId={2}&venderId={3}&cat={4}&_={5}", myProduct.ProductID,
                    SysParams.DispathArea, myProduct.ShopId, myProduct.VenderId, myProduct.Catalog, Golemer.GetTimeStamp(false));
                    string rtnStr = HttpHelper.GetResponseGBK(url, "get", string.Empty);
                    if (string.IsNullOrEmpty(rtnStr) || rtnStr.IndexOf("error", StringComparison.Ordinal) >= 0)
                    {
                        nowTag.IsEnd = true;
                        return;
                    }

                    PromotionMessage promo = JsonConvert.DeserializeObject<PromotionMessage>(rtnStr);
                    if (promo != null)
                    {
                        //myProduct.ProductTag = (promo.ads != null && promo.ads.Count > 0) ? ClearHtml(promo.ads[0].ad) : "";
                        nowTag.Promo = promo.prom.pickOneTag != null && promo.prom.pickOneTag.Count > 0
                            ? Golemer.ClearHtml(promo.prom.pickOneTag[0].content)
                            : "";
                        if (promo.skuCoupon != null && promo.skuCoupon.Count > 0)
                        {
                            //nowTag.Coupon = "";
                            foreach (var item in promo.skuCoupon)
                            {
                                nowTag.Coupon += string.Format("{0}-{1} ", item.quota, item.discount);
                            }
                        }
                    }
                    nowTag.IsEnd = true;
                }
                //if (_waresStatu.ContainsKey(myProduct.ProductID))
                //{
                //    _waresStatu[myProduct.ProductID] = true;
                //}
            }
            catch (Exception ex)
            {
                Faster.XLogErr(ex.Message);
            }
        }
    }
    /// <summary>
    /// 初次采集任务
    /// </summary>
    [DisplayName("商品采集工作项")]
    public class JdBaseWork : IWorkItem
    {
        /// <summary>
        /// 编号
        /// </summary>
        public int ID { get; set; }
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 优先级
        /// </summary>
        public int Priority { get; set; }
        /// <summary>
        /// 工作内容
        /// </summary>
        public Object WorkItems { get; set; }
        /// <summary>
        /// 状态
        /// </summary>
        public EnumGatherStatu Statu { get; internal set; }
        /// <summary>
        /// 返回结果集
        /// </summary>
        public object ResultItems { get; internal set; }

        /// <summary>
        /// 时长
        /// </summary>
        public int Time { get; set; }

        public void ExecItem()
        {
            throw new NotImplementedException();
        }
    }
    /// <summary>
    /// 商品搜索工作项
    /// </summary>
    [DisplayName("商品搜索工作项")]
    public class JdSearchWork : IWorkItem
    {
        /// <summary>
        /// 编号
        /// </summary>
        public int ID { get; set; }
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 优先级
        /// </summary>
        public int Priority { get; set; }
        /// <summary>
        /// 工作内容
        /// </summary>
        public Object WorkItems { get; set; }
        /// <summary>
        /// 状态
        /// </summary>
        public EnumGatherStatu Statu { get; internal set; }
        /// <summary>
        /// 返回结果集
        /// </summary>
        public object ResultItems { get; internal set; }

        /// <summary>
        /// 时长
        /// </summary>
        public int Time { get; set; }

        public void ExecItem()
        {
            ResultItems = GetSearchList(WorkItems.ToString());
        }

        private string GetURLResult(string website)
        {
            try
            {
                if (string.IsNullOrEmpty(website))
                {
                    return null;
                }
                HttpItem item = new HttpItem();
                SFHttpHelper helper = new SFHttpHelper();
                HttpResult result = new HttpResult();
                item.URL = website;
                item.Encoding = Encoding.UTF8;
                item.Header.Add("Accept-Encoding", "gzip, deflate");
                item.ContentType = "text/html";
                item.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)";
                item.Cookie = "unick=%E8%B5%96%E7%9A%AE%E9%B9%8F; _pst=; __jdv=122270672|shop.beva.com|t_328130888_|tuiguang|138ba3ffa5e749eda05260183d68b1e5; unpl=V2_ZzNtbUAEQRZyChJVKExVB2IEEwlLXxQVfQ8UXH4QCwVvABtZclRCFXIUR11nGFsUZwMZXENcQhNFC3ZWfhhcA2UCEFtyZ0sdGwh2V3spXARnMxteRlBHFXULRGRLGVo1ZwoaXUdWQSUxZkFVKx0JAm5XRl4VU0YlaQh2VUsYbEhuABZaRldDFnc4R2R4; jdAddrId=; jdAddrName=; areaId=22; rkv=V09; __jda=122270672.825651123.1469948136.1470536471.1470549502.4; __jdb=122270672.3.825651123|4.1470549502; __jdc=122270672; ipLoc-djd=22-1930-50949-52154; ipLocation=%u56DB%u5DDD; mx=0_X; xtest=45532.29042.14ee22eaba297944c96afdbe5b16c65b.14ee22eaba297944c96afdbe5b16c65b; __jdu=825651123";
                result = helper.GetHtml(item);
                return result.Html;
            }
            catch (Exception ex)
            {
                ImportThreads.LastMsg = "失败：未获取到网页数据";
                Debug.WriteLine(ex.Message);
                return null;
            }
            //string rtn = HttpHelper.GetResponseUTF(url, "get", string.Empty);
            //return rtn;
        }

        readonly List<WebSiteModel> _sites = new List<WebSiteModel>();

        private void ParseResult(string rtn)
        {
            
            MatchCollection wNameList = Regex.Matches(rtn, "<a target=\"_blank\" title=\"(.*)\"\\s*href=\"//item.jd.com/\\d{1,14}.html\"\\s*onclick=\"(.*)\">\\s*<em>");
            for (int i = 0; i < wNameList.Count; i++)
            {
                string tt = wNameList[i].Value;
                string wUrl = Regex.Match(tt, "//item.jd.com/\\d{1,14}.html").Value;
                string wName = Regex.Match(tt, "title=\"(.*)\" ").Value.Replace("title=", "");
                if (!_sites.Exists(t => t.url == wUrl))
                {
                    _sites.Add(new WebSiteModel()
                    {
                        title = wName,
                        url = wUrl
                    });
                }
            }
        }

        /// <summary>
        /// 获取商品检索结果
        /// </summary>
        /// <param name="keyword">关键词</param>
        /// <returns>网站数据列表</returns>
        public List<WebSiteModel> GetSearchList(string keyword)
        {
            if (string.IsNullOrEmpty(keyword))
            {
                return null;
            }
            #region 说明
            //搜索结果（第一页）
            //http://search.jd.com/Search?keyword=%E5%B0%8F%E9%BA%A6%E7%8E%8B%E5%95%A4%E9%85%92&enc=utf-8&suggest=1.his.0&wq=&pvid=q1r6s1ni.7uj14o
            //http://search.jd.com/Search?keyword=%E8%92%99%E7%89%9B&enc=utf-8&wq=%E8%92%99%E7%89%9B&pvid=do2gzjri.fhkknd
            //http://search.jd.com/Search?keyword=%E7%89%B9%E4%BB%91%E8%8B%8F&enc=utf-8&pvid=4seb1kri.fhkknd
            //第二页
            //http://search.jd.com/Search?keyword=%E5%8D%8E%E4%B8%BA&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&bs=1&ev=exbrand_%E5%8D%8E%E4%B8%BA%EF%BC%88HUAWEI%EF%BC%89%40&page=11&s=301&click=0
            //http://search.jd.com/Search?keyword=%E8%92%99%E7%89%9B&enc=utf-8&wq=%E8%92%99%E7%89%9B&pvid=o7m60kri.fhkknd#keyword=%E8%92%99%E7%89%9B&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&offset=1&page=3&s=60&click=0
            //第三页
            //http://search.jd.com/Search?keyword=%E8%92%99%E7%89%9B&enc=utf-8&wq=%E8%92%99%E7%89%9B&pvid=do2gzjri.fhkknd#keyword=%E8%92%99%E7%89%9B&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&offset=1&page=5&s=120&click=0
            //第四页
            //http://search.jd.com/Search?keyword=%E8%92%99%E7%89%9B&enc=utf-8&wq=%E8%92%99%E7%89%9B&pvid=o7m60kri.fhkknd#keyword=%E8%92%99%E7%89%9B&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&offset=1&page=7&s=180&click=0
            //京东配送
            //http://search.jd.com/Search?keyword=%E7%89%B9%E4%BB%91%E8%8B%8F&enc=utf-8&wq=teluns&pvid=qh570kri.fhkknd#keyword=%E7%89%B9%E4%BB%91%E8%8B%8F&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&offset=1&wtype=1&click=1
            /*<div id="J_topPage" class="f-pager">
						<span class="fp-text">
							<b>1</b><em>/</em><i>178</i>
						</span>
						<a class="fp-prev disabled" href="javascript:;">&lt;</a>
						<a class="fp-next" href="javascript:;">&gt;</a>
					</div>
					<div class="f-result-sum">共<span id="J_resCount" class="num">5311</span>件商品</div>
             * <em><font class="skcolor_ljg">哈尔滨</font>（Harbin） <font class="skcolor_ljg">小麦王</font>啤酒330ml*4*6听  整箱装</em>
             * //item.jd.com/2600210.html
             * <a target="_blank" title="哈尔滨（Harbin） 小麦王啤酒330ml*4*6听  整箱装" href="//item.jd.com/1154022.html" onclick="searchlog(1,1154022,1,1,'','flagsClk=648')">
							<em><font class="skcolor_ljg">哈尔滨</font>（Harbin） <font class="skcolor_ljg">小麦王</font>啤酒330ml*4*6听  整箱装</em>
             */
            #endregion 说明

            string url = string.Format("http://search.jd.com/Search?keyword={0}&enc=utf-8&pvid=4seb1kri.fhkknd", keyword);
            string rtn = GetURLResult(url);
            if (!string.IsNullOrEmpty(rtn))
            {
                string pageNum = Regex.Match(rtn, @"<i>\d{1,3}</i>").Value;
                string sPageNum = Regex.Match(rtn, "page_count:\"12\"").Value;
                if (!string.IsNullOrEmpty(pageNum))
                {
                    
                    //获取商品数量及页数
                    string wareNum = Regex.Match(rtn, "<div class=\"f-result-sum\">共<span id=\"J_resCount\" class=\"num\">\\d{1,4}</span>件商品</div>").Value;
                    //商品数量
                    int wNum = 0;
                    if (!string.IsNullOrEmpty(wareNum))
                    {
                        wNum = int.Parse(Regex.Match(wareNum, "\\d{1,4}").Value);
                    }
                    //总页数
                    int iPageNum = int.Parse(pageNum.Replace("<i>", "").Replace("</i>", ""));
                    pageNum = Regex.Match(sPageNum,"\\d{1,4}").Value;
                    int.TryParse(pageNum, out iPageNum);
                    //int iPageNum = 0;
                    //int.TryParse(iPageNum, out iPageNum);

                    ParseResult(rtn);
                    int iCount = 1;
                    const int multiplier = 60;
                    int iNowPage = 3;
                    for (int i = 2; i < iPageNum; i++)
                    {
                        //keyword=蒙牛牛奶
                        //ev=exbrand_蒙牛@
                        //http://search.jd.com/Search?keyword=%E8%92%99%E7%89%9B%E7%89%9B%E5%A5%B6&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&bs=1&ev=exbrand_%E8%92%99%E7%89%9B%40&page=3&s=61&click=0
                        //http://search.jd.com/Search?keyword={0}&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&bs=1&ev=exbrand_%E8%92%99%E7%89%9B%40&page={1}&s={2}&click=0
                        //http://search.jd.com/Search?keyword={0}&enc=utf-8&wq={0}&pvid=o7m60kri.fhkknd#keyword={0}&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&offset=1&page={1}&s={2}&click=0
                        url = string.Format("http://search.jd.com/Search?keyword={0}&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&bs=1&page={1}&s={2}&click=0",
                                keyword, iNowPage, iCount * multiplier);
                        rtn = GetURLResult(url);
                        ParseResult(rtn);
                        iNowPage += 2;
                        iCount++;
                    }
                    
                }
            }

            return _sites;
        }
    }
    /// <summary>
    /// 商品导入工作项
    /// </summary>
    [DisplayName("商品导入工作项")]
    public class JdImportWork : IWorkItem
    {
        /// <summary>
        /// 编号
        /// </summary>
        public int ID { get; set; }
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 优先级
        /// </summary>
        public int Priority { get; set; }
        /// <summary>
        /// 工作内容
        /// </summary>
        public Object WorkItems { get; set; }
        /// <summary>
        /// 状态
        /// </summary>
        public EnumGatherStatu Statu { get; internal set; }
        /// <summary>
        /// 返回结果集
        /// </summary>
        public object ResultItems { get; internal set; }

        /// <summary>
        /// 时长
        /// </summary>
        public int Time { get; set; }

        public void ExecItem()
        {
            throw new NotImplementedException();
        }
    }
}
